/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package lispinterpreter;

/**
 * Esta clase evalua si el string ingresado cumple la sintaxis de Lisp y la
 * transforma a un objeto LispList.
 * 
 * @author JuanFer
 */
public class LispParser {

    public LispList initialParse(String chain) {
	LispList semiParsedList = new LispList();
	String atomString = "";
	chain = removeFirstLastSpaces(removeFirstLastParenthesis(removeExtraSpaces(chain)));
	int atomLength = 0;
	for (int i = 0; i < chain.length(); i++) {
	    if (chain.charAt(i) == ' ') {
		atomString = chain.substring(i - atomLength, i);
		semiParsedList.addElement(atomInstance(atomString));
		atomLength = 0;
	    } else {
		atomLength++;
	    }
	}
	return semiParsedList;
    }

    /**
     * 
     * @pre String a parsear es una lista simple de Lisp (no tiene sublistas) y
     *      esta bien definida.
     * @param chain
     * @return LispList
     */
    public static LispList parseSimple(String chain) {
	LispList simpleList = new LispList();
	String atom = "";
	chain = removeFirstLastSpaces(removeFirstLastParenthesis(removeExtraSpaces(chain)));
	int lastSpace = chain.lastIndexOf(' ');
	int lastAtomEnded = 0;
	if (chain.length() == 2) {
	    return new LispAtom(false);
	}
	for (int i = 0; i < chain.length(); i++) {
	    if (i == lastSpace) {
		atom = chain.substring(i);
		simpleList.addElement(atomInstance(atom));
	    }
	    if (chain.charAt(i) == ' ') {
		atom = chain.substring(lastAtomEnded, i);
		lastAtomEnded = i + 1;
		simpleList.addElement(atomInstance(atom));
	    }
	}

	return simpleList;
    }

    public boolean formulaIsSimple(String chain) {
	return rightPlacedParenthesisSimple(chain)
		&& twoParenthesisSimple(chain);
    }

    public boolean rightPlacedParenthesisSimple(String chain) {
	if (chain.charAt(0) == '(' && chain.charAt(chain.length() - 1) == ')') {
	    return true;
	} else {
	    return false;
	}
    }

    public boolean twoParenthesisSimple(String chain) {
	int count = 0;
	for (int i = 0; i < chain.length(); i++) {
	    if (chain.charAt(i) == '(') {
		count++;
	    }
	    if (chain.charAt(i) == ')') {
		count++;
	    }
	}
	return (count == 2);

    }

    public static String removeExtraSpaces(String chain) {
	int nextConsecutiveSpacesNumber = 0;
	boolean lastCharWasEspace = true;
	String space = " ";
	for (int i = 0; i < chain.length(); i++) {
	    if (chain.charAt(i) == ' ') {
		nextConsecutiveSpacesNumber++;
		lastCharWasEspace = true;

	    } else {
		if (lastCharWasEspace) {
		    if (nextConsecutiveSpacesNumber > 1) {
			chain = chain.substring(0, i + 1
				- nextConsecutiveSpacesNumber)
				+ chain.substring(i);
			i = 0;
		    }
		}
		lastCharWasEspace = false;
		nextConsecutiveSpacesNumber = 0;

	    }
	}

	return chain;
    }

    public static String removeFirstLastParenthesis(String chain) {
	if (chain.charAt(0) == '(') {
	    chain = chain.substring(1);
	}
	if (chain.charAt(chain.length() - 1) == ')') {
	    chain = chain.substring(0, chain.length() - 1);
	}
	return chain;
    }

    public static String removeFirstLastSpaces(String chain) {
	if (chain.charAt(0) == ' ') {
	    chain = chain.substring(1);
	}
	if (chain.charAt(chain.length() - 1) == ' ') {
	    chain = chain.substring(0, chain.length() - 1);
	}
	return chain;
    }

    public static LispList atomInstance(String atom) {
	LispAtom newAtom;
	if (LispAtom.typeIdentifier(atom) == LispAtom.ATOM_TYPE_FLOAT) {
	    return newAtom = new LispAtom(Float.parseFloat(atom));
	}
	if (LispAtom.typeIdentifier(atom) == LispAtom.ATOM_TYPE_BOOLEAN) {
	    if (atom.charAt(0) == 'T') {
		return newAtom = new LispAtom(true);
	    } else {
		return newAtom = new LispAtom(false);
	    }
	}
	if (LispAtom.typeIdentifier(atom) == LispAtom.ATOM_TYPE_STRING) {
	    return newAtom = (new LispAtom(atom));
	}
	return newAtom = new LispAtom(false);

    }

}
